# coding: utf-8


import os
import tempfile
from subprocess import PIPE, Popen

from django.template import Template, Context

from .base import Base

ONLINE_CONSUMER_URL = 'opstask.redis'


def get_inventory_path(targets):
    _, path_to_file = tempfile.mkstemp()

    with open(path_to_file, 'w') as f:
        for host, port in targets.items():
            f.write('{} ansible_ssh_port={}\n'.format(host, port))
    return path_to_file


SHELL_TEMPLATE = '''
---
- hosts: all
{% if sudo%}
  sudo: true
{%endif%}
{% if sudo_user %}
  sudo_user: {{sudo_user}}
{% endif%}
  tasks:
    - name: {{task_name}}
      script: {{script_path}} {{extras_args}}
'''


def run_command(command, env={}, cwd=None):

    try:
        if cwd:
            run = Popen(command, stdout=PIPE, stderr=PIPE, env=env, cwd=cwd)
        else:
            run = Popen(command, stdout=PIPE, stderr=PIPE, env=env)
    except Exception as e:
        output = 'Popen Exception: {} msg: {}'.format(e.__class__, e)
        status = 'F'
        return status, output

    try:
        output, status = run.communicate()
    except Exception as e:
        output = 'Communicate Exception: {} msg: {}'.format(e.__class__, e)

    if run.returncode != 0:
        status = 'F'
    else:
        status = 'S'
    return status, output


class Shell(Base):

    FIELDS = ('sudo', 'sudo_user', 'task_name', 'script_path')
    DEFAULT_SSH_PORT = 50718

    def validate(self):
        if not self.task_path or not os.path.exists(self.task_path) or not os.path.isfile(self.task_path) or \
                not self._run or not self._workspace or not self._inventory:
            return False
        return True

    def build(self):
        '''
        context = { 'sudo': False,'task_name': 'test_run_memcached', 'script_path': '/tmp/1.sh','extras_args': '-port 10086 -host 0.0.0.0'}
        :return:
        '''
        context = {
            'sudo': False, 'sudo_user': None, 'task_name': self.task_name,
            'script_path': self.task_path, 'extras_args': ''
        }
        if self.kwargs.has_key('sudo'):
            context['sudo'] = self.kwargs.pop('sudo')
        if self.kwargs.has_key('sudo_user'):
            context['sudo_user'] = self.kwargs.pop('sudo_user')
        if self.kwargs.has_key('run_user'):
            context['sudo_user'] = self.kwargs.pop('run_user')
            context['sudo'] = True

        extras_args = ''
        for k, v in self.kwargs.items():
            extras_args += '--{0} {1} '.format(k, v)
        context['extras_args'] = extras_args

        context = Context(context)
        template = Template(SHELL_TEMPLATE)
        render = template.render(context)

        _, path = tempfile.mkstemp()
        with open(path, 'w') as f:
            f.write(render)
        self._run = path
        self._workspace = tempfile.mkdtemp()
        self.build_inventory()

    def build_inventory(self):
        if isinstance(self.hosts, basestring):
            self.hosts = self.hosts.split(',')
        targets = {}
        for host in self.hosts:
            if ':' in host:
                host, port = host.split(':')
                targets[host] = port
            else:
                targets[host] = self.DEFAULT_SSH_PORT
        self._inventory = get_inventory_path(targets)

    def _execute(self):
        if not self.validate():
            return 'F', 'Validate_field: run: {} workspace: {} inventory: {}'.format(
                self._run, self._workspace, self._inventory)
        command = ['/bin/ansible-playbook', self._run, '-i', self._inventory]
        env = os.environ.copy()
        env['JOB_ID'] = self.task_id
        env['ONLINE_CONSUMER_URL'] = ONLINE_CONSUMER_URL

        status, output = run_command(command, env=env, cwd=self._workspace)
        return status, output

    def finished(self):
        if self._run:
            os.remove(self._run)
        if self._inventory:
            os.remove(self._inventory)
        if self._workspace:
            os.removedirs(self._workspace)


def run_task(**context):
    if not isinstance(context, dict) or not context.has_key('task_path') or not context.has_key('task_name') or\
            not context.has_key('task_id') or not context.has_key('task_hosts'):
        return 'F', 'Validate field: '
    task_id = context.pop('task_id')
    task_name = context.pop('task_name')
    task_path = context.pop('task_path')

    status, output = Shell(task_name=task_name, task_id=task_id, task_path=task_path, **context).run()
    return status, output


def test():
    context = {
        'task_id': '1-2-3-4-5-6-',
        'task_name': 'test_run_script',
        'task_path': '/data/daedalus/resources/tasks/service/start_memcached_port.sh',
        'port': 50718,
        'task_hosts': ['172.16.1.115', '172.16.1.123']
    }
    status, output =  run_task(**context)
    print output

if __name__ == "__main__":
    test()